"""
An example of the fleet state prediction.
"""
import numpy as np

import common
import input
import decisions

# Read the input data.
graph, time0, state0, simulator = input.read_data("data/graph.xlsx",
                                                  "data/ice.xlsx",
                                                  "data/ships.xlsx")

# Find the ship that will be ready first.
min_wait = np.timedelta64(1, "Y").astype("timedelta64[h]")
argmin_wait = None
for request in simulator.requests:
    wait = request.time - time0
    if wait < min_wait:
        min_wait = wait
        argmin_wait = request
request = argmin_wait

# Find the icebreaker nearest to the first ship.
min_move = np.inf
argmin_move = None
for icebreaker_name, icebreaker_state in state0.icebreakers.items():
    node = icebreaker_state.node
    move = common.angular_distance(node.lat, node.lon, request.node_start.lat, request.node_start.lon)
    if move < min_move:
        min_move = move
        argmin_move = icebreaker_name, icebreaker_state
name_icebreaker, state_icebreaker = argmin_move

# Initialize the program.
program_icebreaker = decisions.Program()

# Find the path from the icebreaker to the ship.
path_edges, path_length = graph.find_path(state_icebreaker.node.index, request.node_start.index)

# Update the program.
for edge in path_edges:
    program_icebreaker.decisions.append(decisions.Move(edge))

# Update the program.
program_icebreaker.decisions.append(decisions.Attach(request.name))

# Find the path to the destination.
path_edges, path_length = graph.find_path(request.node_start.index, request.node_end.index)

# Update the program.
for edge in path_edges:
    program_icebreaker.decisions.append(decisions.Move(edge))

# Update the program.
program_icebreaker.decisions.append(decisions.Detach(request.name))

# Predict the fleet state after implementation of the decisions.
time1, state1 = simulator.compute(time0, state0, {name_icebreaker: program_icebreaker})
